package com.yixing.tech.system.service.impl;

import org.apache.commons.lang3.StringUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.yixing.tech.common.base.BaseMongoDao;
import com.yixing.tech.common.base.BusinessException;
import com.yixing.tech.common.base.Page;
import com.yixing.tech.common.base.PageRow;
import com.yixing.tech.common.enums.ErrCode;
import com.yixing.tech.common.enums.YesOrNo;
import com.yixing.tech.common.vo.s5.EntitySchema;
import com.yixing.tech.system.po.*;
import com.yixing.tech.system.service.IApplicationService;
import com.yixing.tech.common.utils.DataUtil;
import com.yixing.tech.common.vo.s3.ApplicationVO;
import com.yixing.tech.common.vo.s3.MenuVO;
import lombok.extern.slf4j.Slf4j;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author yixing tech
 * at 2022/3/16
 * describe：
 */
@Service
@Slf4j
public class ApplicationImpl implements IApplicationService {

    @Resource
    BaseMongoDao baseMongoDao;
    @Resource
    MongoTemplate mongoTemplate;
    @Value("${official-tenant-id}")
    private String officialTenantId;

    @Override
    public void add(ApplicationVO applicationVO) throws BusinessException {

        ApplicationVO condition = new ApplicationVO();
        condition.setName(applicationVO.getName());
        if (baseMongoDao.exists(condition, Application.class)) {
            throw new BusinessException(ErrCode.APPLICATION_EXISTED);
        }
        Application po = DataUtil.o2o(applicationVO, Application.class);
        po.setId(null);
        baseMongoDao.save(po);
    }

    @Override
    public void batchAdd(List<ApplicationVO> list) throws BusinessException {

    }

    @Override
    public ApplicationVO queryById(String id) {
        ApplicationVO app = DataUtil.o2o(baseMongoDao.get(id, Application.class), ApplicationVO.class);
        return app;
    }

    @Override
    public List<ApplicationVO> queryByIds(List<String> ids) {
        return null;
    }

    @Override
    public ApplicationVO queryByCondition(ApplicationVO applicationVO) throws BusinessException {
        return null;
    }

    @Override
    public void update(ApplicationVO applicationVO) throws BusinessException {
        Application app = DataUtil.o2o(applicationVO, Application.class);
        baseMongoDao.update(app);
    }

    @Override
    public Page<ApplicationVO> list(PageRow<ApplicationVO> pageRow) {
        return baseMongoDao.listPage(pageRow, Application.class, ApplicationVO.class);
    }

    @Override
    public List<ApplicationVO> list(ApplicationVO condition) {
        return null;
    }

    @Override
    public List<ApplicationVO> list(ApplicationVO condition, String userId) {
        User user = baseMongoDao.get(userId, User.class);
        List<ApplicationVO> apps;
        if (user.getIsSuper()) {
            apps = baseMongoDao.list(condition, Application.class, ApplicationVO.class);
        } else {
            Role role = user.getRole();
            role = baseMongoDao.get(role.getId(), Role.class);
            List<String> appIds = role.getApplicationIds();
            apps = baseMongoDao.batchQuery(appIds, Application.class, ApplicationVO.class);
        }
        return apps;
    }

    @Override
    public void clone(String appId, String tenantId) throws BusinessException {
        Application app = baseMongoDao.get(appId, Application.class);
        app.setTenantId(officialTenantId);
        app.setId(null);
        app = baseMongoDao.save(app);
        String newAppId = app.getId();
        app = new Application();
        app.setId(newAppId);
        ApplicationVO vo = new ApplicationVO();
        vo.setId(appId);
        MenuVO cond = new MenuVO();
        cond.setApplication(vo);
        List<Menu> menus = baseMongoDao.list(cond, Menu.class, Menu.class);
        Map<String, String> objTemp = new HashMap<>();
        for (Menu menu : menus) {
            String parentId = menu.getParentId();
            WebPage webPage = menu.getWebPage();
            if (ObjectUtils.isEmpty(parentId) && webPage == null) {
                menu.setTenantId(tenantId);
                menu.setApplication(app);
                menu.setId(null);
                Menu m = baseMongoDao.save(menu);
                log.error("----menu-----: " + m.getId());
            } else {
                if (webPage != null && !StringUtils.isEmpty(webPage.getId())) {
                    webPage = baseMongoDao.get(webPage.getId(), WebPage.class);
                    if (webPage == null) continue;
                    Dict dict = webPage.getType();
                    String uri = webPage.getUri();
                    if (!StringUtils.isEmpty(uri)) {
                        String type = dict.getId();
                        if ("624e5135a6b9f60c62bc2b9b".equals(type)) {
                            //对象
                            webPage.setUri(cloneObj(uri, tenantId, objTemp));
                        } else if ("6288fc1218f0bf7905b2e1e7".equals(type)) {
                            //树形
                            /**
                             * { "id": "632012bb2ea60c3afeccb174",
                             * "leftTree": {
                             * "enable": true, "form": {}, "attrs": [ { "id": "selectGroup", "name": "合同选择", "type": "obj", "reference": "632011162ea60c3afeccb173", "treeEnable": true, "treeShow": true, "treeMultiple": false } ],
                             * "tableConditions": { "selectGroup": [ { "key": "所属合同.id", "value": [], "symbol": "in" } ] }
                             * }
                             * }
                             */
                            JSONObject jo = JSON.parseObject(uri);
                            String rightObjId = jo.getString("id");
                            String leftObjId = jo.getJSONObject("leftTree").getJSONArray("attrs").getJSONObject(0).getString("reference");
                            jo.put("id", cloneObj(rightObjId, tenantId, objTemp));
                            jo.getJSONObject("leftTree").getJSONArray("attrs").getJSONObject(0).put("reference", cloneObj(leftObjId, tenantId, objTemp));
                            webPage.setUri(jo.toJSONString());
                        }
                        webPage.setTenantId(tenantId);
                        webPage.setId(null);
                        webPage = baseMongoDao.save(webPage);
                        log.error("----webPage-----: " + webPage.getId());
                    }
                }
            }
        }
    }

    private String cloneObj(String objId, String tenantId, Map<String, String> objTemp) {
        String newObjId = objTemp.get(objId);
        if (StringUtils.isEmpty(newObjId)) {
            EntitySchema objVO = mongoTemplate.findById(new ObjectId(objId), EntitySchema.class, "obj");
            objVO.setId(null);
            objVO.setTenantId(tenantId);
            objVO = mongoTemplate.save(objVO, "obj");
            newObjId = objVO.getId();
            log.error("----objVO-----: " + newObjId);
            objTemp.put(objId, newObjId);
        }
        return newObjId;
    }

    @Override
    public void deleteById(String id) throws BusinessException {
        Application app = new Application();
        app.setId(id);
        app.setIsDelete(YesOrNo.YES.ordinal());
        baseMongoDao.update(app);
    }

    @Override
    public void delete(List<String> ids) throws BusinessException {

    }
}
